{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TsHV-7cpVkyK"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "atWM-s8yVnfX"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TB0wBWfcVqHz"
      },
      "source": [
        "# HParams ダッシュボードでハイパーパラメータ調整を行う\n",
        "\n",
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "<img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\"><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/tensorboard/hyperparameter_tuning_with_hparams.ipynb\">TensorFlow.org で表示</a>\n",
        "</td>\n",
        "  <td>\n",
        "<img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\"><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/tensorboard/hyperparameter_tuning_with_hparams.ipynb\">Google Colab で実行</a>\n",
        "</td>\n",
        "  <td>\n",
        "<img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\"><a target=\"_blank\" href=\"https://github.com/tensorflow/tensorboard/blob/master/docs/hyperparameter_tuning_with_hparams.ipynb\">GitHub でソースを表示</a>\n",
        "</td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "elH58gbhWAmn"
      },
      "source": [
        "機械学習モデルを構築する際、レイヤーのドロップアウト率や学習率などのさまざまな[ハイパーパラメータ](https://en.wikipedia.org/wiki/Hyperparameter_(machine_learning))を選択する必要があります。この判断によって制度などのモデルメトリックに影響があります。したがって、問題に最適なハイパーパラメータを特定することが機械学習ワークフローの重要なステップであり、多くの場合、実験が伴います。このプロセスは「ハイパーパラメータ最適化」または「ハイパーパラメータ調整」として知られています。\n",
        "\n",
        "TensorBoard の HParams ダッシュボードには、ハイパーパラメータの最適な実験または最も有望なセットを特定するプロセスを支援するツールがいくつか提供されています。\n",
        "\n",
        "このチュートリアルでは、次のステップに焦点を当てています。\n",
        "\n",
        "1. セットアップと HParams の要約を実験する\n",
        "2. ハイパーパラメータとメトリックをログするように TensorFlow 実行を適応させる\n",
        "3. 実行を開始し、1 つの親ディレクトリにすべてをログする\n",
        "4. TensorBoard の HParams ダッシュボードに結果を視覚化する\n",
        "\n",
        "注意: HParams summary API とダッシュボード UI はプレビュー段階であるため、いずれ変更されます。\n",
        "\n",
        "TF 2.0 をインストールし、TensorBoard ノートブック拡張機能を読み込んで起動します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "id": "8p3Tbx8cWEFA"
      },
      "outputs": [],
      "source": [
        "# Load the TensorBoard notebook extension\n",
        "%load_ext tensorboard"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "lEWCCQYkWIdA"
      },
      "outputs": [],
      "source": [
        "# Clear any logs from previous runs\n",
        "!rm -rf ./logs/ "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9GtR_cTTkf9G"
      },
      "source": [
        "TensorFlow と TensorBoard HParams プラグインをインポートします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "mVtYvbbIWRkV"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "from tensorboard.plugins.hparams import api as hp"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XfCa27_8kov6"
      },
      "source": [
        "[FashionMNIST](https://github.com/zalandoresearch/fashion-mnist) データセットをダウンロードし、スケーリングします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "z8b82G7YksOS"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz\n",
            "32768/29515 [=================================] - 0s 0us/step\n",
            "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz\n",
            "26427392/26421880 [==============================] - 0s 0us/step\n",
            "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz\n",
            "8192/5148 [===============================================] - 0s 0us/step\n",
            "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz\n",
            "4423680/4422102 [==============================] - 0s 0us/step\n"
          ]
        }
      ],
      "source": [
        "fashion_mnist = tf.keras.datasets.fashion_mnist\n",
        "\n",
        "(x_train, y_train),(x_test, y_test) = fashion_mnist.load_data()\n",
        "x_train, x_test = x_train / 255.0, x_test / 255.0"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0tsTxO85WaYq"
      },
      "source": [
        "## 1. セットアップと HParams の実験要約を実験する\n",
        "\n",
        "モデルの 3 つのハイパーパラメータを使って実験します。\n",
        "\n",
        "1. 最初の密レイヤーのユニット数\n",
        "2. ドロップアウトレイヤーのドロップアウト率\n",
        "3. オプティマイザ\n",
        "\n",
        "試す値をリストして、実験構成を TensorBoard にログします。このステップはオプションですが、UI でハイパーパラメータをより正確にフィルタリングして表示するメトリックを指定できるようにドメイン情報を指定することができます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "5Euw0agpWb4V"
      },
      "outputs": [],
      "source": [
        "HP_NUM_UNITS = hp.HParam('num_units', hp.Discrete([16, 32]))\n",
        "HP_DROPOUT = hp.HParam('dropout', hp.RealInterval(0.1, 0.2))\n",
        "HP_OPTIMIZER = hp.HParam('optimizer', hp.Discrete(['adam', 'sgd']))\n",
        "\n",
        "METRIC_ACCURACY = 'accuracy'\n",
        "\n",
        "with tf.summary.create_file_writer('logs/hparam_tuning').as_default():\n",
        "  hp.hparams_config(\n",
        "    hparams=[HP_NUM_UNITS, HP_DROPOUT, HP_OPTIMIZER],\n",
        "    metrics=[hp.Metric(METRIC_ACCURACY, display_name='Accuracy')],\n",
        "  )"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "T_T95RrSIVO6"
      },
      "source": [
        "このステップを省略する場合は、`hparams[HP_DROPOUT]` の代わりに `hparams['dropout']` を指定するように、`HParam` 値を使用する箇所に文字列リテラル使用できます。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "va9XMh-dW4_f"
      },
      "source": [
        "## 2. ハイパーパラメータとメトリックをログするように TensorFlow 実行を適応させる\n",
        "\n",
        "モデルは、2 つの密レイヤーとその間にドロップアウトレイヤーを使用する、非常に簡単なモデルになります。トレーニングコードは似ていますが、ハイパーパラメータはハードコードされていません。その代わり、`hparams` ディクショナリにハイパーパラメータを指定し、トレーニング関数で使用します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "hG-zalNfW5Zl"
      },
      "outputs": [],
      "source": [
        "def train_test_model(hparams):\n",
        "  model = tf.keras.models.Sequential([\n",
        "    tf.keras.layers.Flatten(),\n",
        "    tf.keras.layers.Dense(hparams[HP_NUM_UNITS], activation=tf.nn.relu),\n",
        "    tf.keras.layers.Dropout(hparams[HP_DROPOUT]),\n",
        "    tf.keras.layers.Dense(10, activation=tf.nn.softmax),\n",
        "  ])\n",
        "  model.compile(\n",
        "      optimizer=hparams[HP_OPTIMIZER],\n",
        "      loss='sparse_categorical_crossentropy',\n",
        "      metrics=['accuracy'],\n",
        "  )\n",
        "\n",
        "  model.fit(x_train, y_train, epochs=1) # Run with 1 epoch to speed things up for demo purposes\n",
        "  _, accuracy = model.evaluate(x_test, y_test)\n",
        "  return accuracy"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "46oJF8seXM7v"
      },
      "source": [
        "実行のたびに、ハイパーパラメータと最終精度とともに、hparams の要約をログします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "8j-fO6nEXRfW"
      },
      "outputs": [],
      "source": [
        "def run(run_dir, hparams):\n",
        "  with tf.summary.create_file_writer(run_dir).as_default():\n",
        "    hp.hparams(hparams)  # record the values used in this trial\n",
        "    accuracy = train_test_model(hparams)\n",
        "    tf.summary.scalar(METRIC_ACCURACY, accuracy, step=1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2mYdW0VKLbFE"
      },
      "source": [
        "Keras モジュールをトレーニングする際は、直接これらを書き込む代わりにコールバックを使用できます。\n",
        "\n",
        "```python\n",
        "model.fit(\n",
        "    ...,\n",
        "    callbacks=[\n",
        "        tf.keras.callbacks.TensorBoard(logdir),  # log metrics\n",
        "        hp.KerasCallback(logdir, hparams),  # log hparams\n",
        "    ],\n",
        ")\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "u2nOgIKAXdcb"
      },
      "source": [
        "## 3. 実行を開始し、1 つの親ディレクトリにすべてをログする\n",
        "\n",
        "様々なハイパーパラメータのセットを実験ごとに変更してトレーニングし、複数の実験を試せるようになりました。\n",
        "\n",
        "簡単にするために、グリッド検索を使用します。離散パラメータのすべての組み合わせと実際値パラメータの上限と下限を試します。より複雑なシナリオでは、それぞれのハイパーパラメータの値をランダムに選択する方が効果的かもしれません（ランダム検索といいます）。より高度な手法も存在します。\n",
        "\n",
        "実験をいくつか実行します。これには数分かかります。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "KbqT5n-AXd0h"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--- Starting trial: run-0\n",
            "{'num_units': 16, 'dropout': 0.1, 'optimizer': 'adam'}\n",
            "60000/60000 [==============================] - 4s 62us/sample - loss: 0.6872 - accuracy: 0.7564\n",
            "10000/10000 [==============================] - 0s 35us/sample - loss: 0.4806 - accuracy: 0.8321\n",
            "--- Starting trial: run-1\n",
            "{'num_units': 16, 'dropout': 0.1, 'optimizer': 'sgd'}\n",
            "60000/60000 [==============================] - 3s 54us/sample - loss: 0.9428 - accuracy: 0.6769\n",
            "10000/10000 [==============================] - 0s 36us/sample - loss: 0.6519 - accuracy: 0.7770\n",
            "--- Starting trial: run-2\n",
            "{'num_units': 16, 'dropout': 0.2, 'optimizer': 'adam'}\n",
            "60000/60000 [==============================] - 4s 60us/sample - loss: 0.8158 - accuracy: 0.7078\n",
            "10000/10000 [==============================] - 0s 36us/sample - loss: 0.5309 - accuracy: 0.8154\n",
            "--- Starting trial: run-3\n",
            "{'num_units': 16, 'dropout': 0.2, 'optimizer': 'sgd'}\n",
            "60000/60000 [==============================] - 3s 50us/sample - loss: 1.1465 - accuracy: 0.6019\n",
            "10000/10000 [==============================] - 0s 36us/sample - loss: 0.7007 - accuracy: 0.7683\n",
            "--- Starting trial: run-4\n",
            "{'num_units': 32, 'dropout': 0.1, 'optimizer': 'adam'}\n",
            "60000/60000 [==============================] - 4s 65us/sample - loss: 0.6178 - accuracy: 0.7849\n",
            "10000/10000 [==============================] - 0s 38us/sample - loss: 0.4645 - accuracy: 0.8395\n",
            "--- Starting trial: run-5\n",
            "{'num_units': 32, 'dropout': 0.1, 'optimizer': 'sgd'}\n",
            "60000/60000 [==============================] - 3s 55us/sample - loss: 0.8989 - accuracy: 0.6896\n",
            "10000/10000 [==============================] - 0s 37us/sample - loss: 0.6335 - accuracy: 0.7853\n",
            "--- Starting trial: run-6\n",
            "{'num_units': 32, 'dropout': 0.2, 'optimizer': 'adam'}\n",
            "60000/60000 [==============================] - 4s 64us/sample - loss: 0.6404 - accuracy: 0.7782\n",
            "10000/10000 [==============================] - 0s 37us/sample - loss: 0.4802 - accuracy: 0.8265\n",
            "--- Starting trial: run-7\n",
            "{'num_units': 32, 'dropout': 0.2, 'optimizer': 'sgd'}\n",
            "60000/60000 [==============================] - 3s 54us/sample - loss: 0.9633 - accuracy: 0.6703\n",
            "10000/10000 [==============================] - 0s 36us/sample - loss: 0.6516 - accuracy: 0.7755\n"
          ]
        }
      ],
      "source": [
        "session_num = 0\n",
        "\n",
        "for num_units in HP_NUM_UNITS.domain.values:\n",
        "  for dropout_rate in (HP_DROPOUT.domain.min_value, HP_DROPOUT.domain.max_value):\n",
        "    for optimizer in HP_OPTIMIZER.domain.values:\n",
        "      hparams = {\n",
        "          HP_NUM_UNITS: num_units,\n",
        "          HP_DROPOUT: dropout_rate,\n",
        "          HP_OPTIMIZER: optimizer,\n",
        "      }\n",
        "      run_name = \"run-%d\" % session_num\n",
        "      print('--- Starting trial: %s' % run_name)\n",
        "      print({h.name: hparams[h] for h in hparams})\n",
        "      run('logs/hparam_tuning/' + run_name, hparams)\n",
        "      session_num += 1\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qSyjWQ3mPKT9"
      },
      "source": [
        "## 4. TensorBoard の HParams ダッシュボードに結果を視覚化する"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5VBvplwyP8Vy"
      },
      "source": [
        "HParams ダッシュボードを開けるようになったので、TensorBoard を起動して上部にある「HParams」をクリックします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Xf4KM-U2bbP_"
      },
      "outputs": [],
      "source": [
        "%tensorboard --logdir logs/hparam_tuning"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "UTWg9nXnxWWI"
      },
      "source": [
        "<img class=\"tfo-display-only-on-site\" src=\"images/hparams_table.png?raw=1\">"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4RPGbR9EWd4o"
      },
      "source": [
        "ダッシュボードの左ペインには、HParams ダッシュボードのすべてのビューで有効化されているフィルタ機能があります。\n",
        "\n",
        "- ダッシュボードに表示するハイパーパラメータ/メトリックのフィルタリング\n",
        "- ダッシュボードに表示するハイパーパラメータ/メトリックの値のフィルタリング\n",
        "- 実行ステータスによるフィルタリング（実行中、成功、など）\n",
        "- テーブルビューのハイパーパラメータ/メトリックの並べ替え\n",
        "- 表示するセッショングループの数（実験が多数ある場合のパフォーマンスに役立ちます）\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Z3Q5v28XaCt8"
      },
      "source": [
        "HParams ダッシュボードには 3 つのビューがあり、さまざまな有益な情報が表示されます。\n",
        "\n",
        "- **テーブルビュー** には、実行、実行のハイパーパラメータ、およびメトリックがリストされます。\n",
        "- **平行座標ビュー**には、各実行がハイパーパラメータとメトリックの軸を通る線として表示されます。任意の軸をクリックしてドラッグして領域をマークすると、それを通過する実行のみを強調して表示するできます。これはどのハイパーパラメータのグループが最も重要であるかを特定する上で役立ちます。軸自体は、ドラッグして並べ替えることができます。\n",
        "- **散布図ビュー**には、各ハイパーパラメータ/メトリックを各メトリックと比較したプロットが表示されます。こうすることで、相関関係を識別するのに役立ちます。クリックアンドドラッグして特定のプロットの領域を選択すると、ほかのプロットのそれらのセッションを強調して表示できます。\n",
        "\n",
        "テーブル行、平行座標線、および散布図マーケットはクリック可能で、メトリックのプロットをそのセッションのトレーニングステップの関数として表示することができます（このチュートリアルでは、実行ごとに 1 つのステップのみが使用されています）。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fh3p0DtcdOK1"
      },
      "source": [
        "HParams ダッシュボードの機能をさらに探るには、より多くの実験を使用した生成済みのログをダウンロードしてください。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "oxrSUAnCeFmQ"
      },
      "outputs": [],
      "source": [
        "%%bash\n",
        "wget -q 'https://storage.googleapis.com/download.tensorflow.org/tensorboard/hparams_demo_logs.zip'\n",
        "unzip -q hparams_demo_logs.zip -d logs/hparam_demo"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "__8xQhjqgr3D"
      },
      "source": [
        "TensorBoard でログを表示します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "KBHp6M_zgjp4"
      },
      "outputs": [],
      "source": [
        "%tensorboard --logdir logs/hparam_demo"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Po7rTfQswAMT"
      },
      "source": [
        "<img class=\"tfo-display-only-on-site\" src=\"images/hparams_parallel_coordinates.png?raw=1\">"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IlDz2oXBgnZ9"
      },
      "source": [
        "HParams ダッシュボードのさまざまなビューを試してみてください。\n",
        "\n",
        "たとえば、平行座標ビューに移動して、精度軸をクリックアンドドラッグすると、精度の最も高い実行を選択できます。こういった実行はオプティマイザ軸の「adam」を通過するため、実験では「sgd」よりも「adam」の方がより高い性能を見せたと結論付けることができます。"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "hyperparameter_tuning_with_hparams.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
